using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using SynapseGaming.SunBurn.Framework.Core;
using SynapseGaming.SunBurn.Framework.Misc;
using SynapseGaming.SunBurn.Framework.Primitives;
using SynapseGaming.SunBurn.Framework.Input;
using GameLibrary.Input;

namespace GameLibrary
{
    public class Camera
    {
        private float moveSpeed;
        private Vector3 direction;
        private CompositeInputSource inputSources;

        private Vector3 position;
        private Matrix view;

        public float MoveSpeed
        {
            get { return moveSpeed; }
            set { moveSpeed = value; }
        }
        public Matrix View
        {
            get { return view; }
            set { view = value; }
        }

        public Camera()
        {
            moveSpeed = 300.0f;

            position = new Vector3(0.0f, 50.0f, 0.0f);
            direction = Vector3.Normalize(new Vector3(0.68f, -0.25f, 0.68f));

            BaseInputSource[] sources = new BaseInputSource[]
            {
                new GamepadInputSource(0),// accept gamepad input from player 0
                new KeyboardInputSource(),// accept keyboard input
                new MouseInputSource(),// accept touch input
                new TouchInputSource()
            };

            inputSources = new CompositeInputSource(sources);
        }

        private Matrix GetFreeCameraView(float elapsed)
        {
            // Avoid moving with keyboard and mouse when the editor is open.
            float rotatescale = 350.0f * elapsed;
            float movescale = elapsed * moveSpeed;

            Vector3 rotation = Vector3.Zero;

            rotation.X -= MathHelper.ToRadians(inputSources.LookUpDownAmount * rotatescale);
            rotation.Y -= MathHelper.ToRadians(inputSources.TurnAmount * rotatescale);

            Vector3 right = Vector3.Cross(Vector3.Up, direction);

            direction = Vector3.Transform(direction, Matrix.CreateFromAxisAngle(right, rotation.X) *
                Matrix.CreateRotationY(rotation.Y));

            if (direction != Vector3.Zero)
            {
                direction.Normalize();
            }

            right = Vector3.Cross(Vector3.Up, direction);

            position += direction * inputSources.MoveAmount.Y * movescale +
                        right * inputSources.MoveAmount.X * -movescale;

            // Convert the camera rotation and movement into a view transform.
            Vector3 target = position + direction;
            return Matrix.CreateLookAt(position, target, Vector3.Up);
        }

        public void Update(float elapsed)
        {
            KeyboardState keyState = Platform.Instance.InputDevice.KeyboardState;
            MouseState mouseState = Platform.Instance.InputDevice.MouseState;

            inputSources.Update();

            view = GetFreeCameraView(elapsed);
        }
    }
}
